home *** CD-ROM | disk | FTP | other *** search
/ The X-Philes (2nd Revision) / The X-Philes Number 1 (1995).iso / xphiles / hp48_1 / stoer / comp.sys.handhelds_2970_000000.msg
Internet Message Format  |  1995-03-31  |  7KB

  1. From: austern@ux5.lbl.gov (Matt Austern)
  2. Subject: Bulirsch-Stoer integration on the HP 48  (Part 1 of 2)
  3. Summary: Documentation, description, and examples.
  4. Keywords: Bulirsch-Stoer, differential equations
  5. Date: 18 Dec 90 18:13:28 GMT
  6. Organization: Lawrence Berkeley Laboratory (theoretical physics group)
  7.  
  8. I have written a program for the hp 48 which solves systems of
  9. differential equations using the Bulirsch-Stoer algorithm.  This
  10. posting is a description of the program, and the next posting is the code
  11. itself.  
  12.  
  13. SUMMARY OF THE METHOD
  14.  
  15. If you look at the code, it will immediately be apparent that this
  16. algorithm is immensely more complicated than, say, Runge-Kutta.
  17. Although this complexity makes a single step rather slow, the
  18. advantage of Bulirsch-Stoer is that it is often possible to choose
  19. extremely large step sizes while maintaining reasonable accuracy.  
  20.  
  21. The Bulirsch-Stoer algorithm is described in Numerical Recipes, by
  22. Press, Flannery, Teukolsky, and Vettering.  (If you do any numerical
  23. work and you don't already have a copy of that book, by the way, you
  24. should get one.)  I'll give a brief summary, just so that this
  25. program won't be completely a black box.
  26.  
  27. If you have a system of equations of the form y' = f(x, y), where y
  28. and y' are in general vectors, and the initial conditions (x0, y0),
  29. then the problem is to find y(x1) for some x1.  (Normally, we require
  30. x1 - x0 to be small; here, we make no such requirement.)  Define H =
  31. x1 - x0.  
  32.  
  33. We divide H into n subintervals, and then use n iterations of a
  34. simple first-order method (specifically, the modified midpoint
  35. method) to find y(x1).  Define this value to be y(x1, h), where 
  36. h = H/n.
  37.  
  38. The Bulirsch-Stoer algorithm is to compute y(x1, h) for several
  39. different values of h, and then extrapolate down to h=0.  The
  40. extrapolation algorithm provides an estimate of its accuracy; when
  41. this accuracy is good enough, we return the answer.  Convergence is
  42. somewhat quicker than might be expected; it turns out that
  43. y(x1, h) contains only even powers of h, so the extrapolation is
  44. actually in h^2.
  45.  
  46. This algorithm can occasionally fail.  The rational function
  47. extrapolation might encounter a pole, in which case there's nothing
  48. to do but quit.  The program checks for this failure, so that at
  49. least there won't be a mysterious blowup.  (This is rare, but it
  50. happened to me once.  The solution is to use a different
  51. extrapolation procedure in those cases.  If I get energetic, I may
  52. implement polynomial extrapolation for the 48sx as a fallback.)  It
  53. is also conceivable that the step size will have to be reduced so far
  54. that x+h will be indistinguishable from x.  I have never seen this
  55. happen (my guess is that it would only happen when you're close to
  56. some singular point in the solution of the differential equation, or
  57. when you have a system of equations which vary on very different
  58. scales), but there is code to check for that too.
  59.  
  60. THE PROGRAM:
  61.  
  62. There are actually four programs here: EXTRAP, NDESTEP, DESTEP1, and
  63. DE.  (There are also two objects that are intended for internal use.
  64. They are named in lowercase.)
  65.  
  66. EXTRAP is the extrapolation routine.  It takes two arguments, both
  67. lists.  Level 2 contains a list of x values, and level 1 a list of y
  68. values.  EXTRAP returns two values: in level 2 it returns y(0), and
  69. in level 1 an estimate of the error in that prediction.  (EXTRAP,
  70. incidentally, is where most of the time gets spent.  I've tried to
  71. make the code in its inner loop efficient, but I'd welcome any
  72. suggestions for speeding it up.)
  73.  
  74. DESTEP1 solves a single first-order differential equation.  It takes
  75. five arguments.  In order, level 5 to level 1, they are: ydot,
  76. tolerance, stepsize, x, y.  ydot is a function: it takes x and y (on
  77. the stack, in that order) and returns y'(x, y).  Tolerance is the
  78. required accuracy (i.e., if Delta-y is the error, then we demand
  79. Delta-y / y < tolerance), and stepsize, x, and y are
  80. self-explanatory.  DESTEP1 returns the same information, to make it
  81. convenient to take another step.  ydot and tolerance are left
  82. unchanged on the stack; the new step size is that recommended by the
  83. algorithm (you don't have to follow the recommendation, of course!);
  84. and x and y are the new values.
  85.  
  86. (Note: if you are too greedy with your step size and your tolerance,
  87. DESTEP1 might have to choose a smaller step than you asked for.  If
  88. so, x will be incremented by the step actually used.  This is
  89. slightly unusual, though: Bulirsch-Stoer can handle most reasonable
  90. requests.)
  91.  
  92. NDESTEP is just the same, except that y is a vector, and ydot must
  93. take a vectorial y as an argument and return a vectorial ydot as a
  94. result.  (Most of the code in NDESTEP, actually, is identical to that
  95. in DESTEP1.  Merging them would be quite easy if you want to conserve
  96. memory.)
  97.  
  98. DE is intended for interactive use; it's essentially just a
  99. cosmetic shell for NDESTEP and DESTEP1.  It takes and returns only
  100. four arguments: tolerance is taken from the display format.  (In STD
  101. format, it uses a tolerance of 0.0001.)  It chooses to call NDESTEP
  102. or DESTEP1, depending on the type of argument given.  It returns x
  103. and y as tagged objects; if the user provided tags then those tags
  104. are preserved, otherwise it uses the rather unimaginative labels "x"
  105. and "y".  Finally, NDESTEP and DESTEP1 use user flags; DE saves and
  106. restores the old values.
  107.  
  108.  
  109. EXAMPLE PROBLEM:
  110.  
  111. Solve the equation x^2 y''(x)  +  x y'(x)  +  x^2 y(x)  =  0, subject
  112. to the initial conditions y(0) = 1, y'(0) = 0.  Specifically, find y(5).
  113.  
  114. Solution:
  115.  
  116. This is equivalent to the system
  117.     y1'  =  - y1/x  -  y
  118.     y'   =  y1,
  119. with y(0) = 1, y'(0) = 0.
  120.  
  121. Put the following four entries on the stack:
  122. \<< OBJ\-> DROP \-> x y1 y
  123.     \<< IF x 0 == THEN y NEG ELSE y1 x / y + NEG END
  124.         y1 2 \->ARRY
  125.     \>>
  126. \>>
  127. 5
  128. 0
  129. [0 1]
  130.  
  131. Then, with the display mode set to 3 FIX, hit DE.  After 67 seconds,
  132. I get the result that y(5) = -0.178, and y'(5) = 0.328.
  133.  
  134. In fact, the solution to this equation is a Bessel function, J0(x).
  135. The tabulated answer is J0(5) = -0.177597, and J0'(5) = -J1(5) = 0.327579.
  136.  
  137. 67 seconds is a long time, but we were able to span the entire
  138. interval from 0 to 5 in a single step, and still get three digits of
  139. accuracy. 
  140.  
  141.  
  142. Enjoy!  There are obviously better tools than the HP 48 for serious
  143. numerical calculations, but it's very convenient to have a quick way
  144. of playing with a differential equation.
  145. -- 
  146. Matthew Austern    austern@lbl.bitnet     Proverbs for paranoids, 3: If 
  147. (415) 644-2618     austern@ux5.lbl.gov    they can get you asking the wrong 
  148.                    austern@lbl.gov        questions, they don't have to worry
  149.                                           about answers.
  150.